/****************************************************************************
 *
 *  ALi (Shanghai) Corporation, All Rights Reserved. 2008 Copyright (C)
 *
 *  File: win_mpspectrum.c
 *
 *  Description: spectrum analysis
 *              
 *  History:
 *      Date        		Author         	Version   		Comment
 *      ====        		======        =======   	=======
 *	2.	2008.04.29		Sharon Zhang	0.1.001			initial for mediaplayer 2.0
 *
 ****************************************************************************/
#include <sys_config.h>
#ifdef USB_MP_SUPPORT
#include <types.h>
#include <osal/osal.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <api/libosd/osd_lib.h>
#include <hld/snd/snd_dev.h>
#include <hld/snd/snd.h>

#include "osdobjs_def.h"

#include "osd_config.h"
#include "string.id"
#include "images.id"

#include "control.h"

/*******************************************************************************
*	WINDOW's objects declaration
*******************************************************************************/
#define SPECTRUM_BAR_CNT	7
#define SPECTRUM_BAR_STEP			2//1

typedef struct SPECTRUM_INFO
{
	UINT16 bar_peak[SPECTRUM_BAR_CNT];
	UINT16 bar_step[SPECTRUM_BAR_CNT];
	INT32 bar_precent[SPECTRUM_BAR_CNT];
}spectrum_info;

#define BAR_MIN_POS		0
#define BAR_MAX_POS		100

extern CONTAINER 		spectrum_con;

extern PROGRESS_BAR		spectrum_bar_0; 
extern BITMAP			spectrum_peak_0;

extern PROGRESS_BAR		spectrum_bar_1; 
extern BITMAP			spectrum_peak_1;

extern PROGRESS_BAR		spectrum_bar_2; 
extern BITMAP			spectrum_peak_2;

extern PROGRESS_BAR		spectrum_bar_3; 
extern BITMAP			spectrum_peak_3;

extern PROGRESS_BAR		spectrum_bar_4; 
extern BITMAP			spectrum_peak_4;

extern PROGRESS_BAR		spectrum_bar_5; 
extern BITMAP			spectrum_peak_5;

extern PROGRESS_BAR		spectrum_bar_6; 
extern BITMAP			spectrum_peak_6;

/*******************************************************************************
*	Macro definition
*******************************************************************************/
#define SPECTRUM_CON_SH_IDX		WSTL_MP_MUTE_BG_HD//WSTL_TEXT_05_HD//WSTL_PREV_01
#define B_BG_SH_IDX				WSTL_MP_MUTE_BG_HD //WSTL_MP_SPCTRM_GRAY_HD
#define B_MID_SH_IDX			WSTL_MP_SPCTRM_BAR_HD

//same as FL_INFO_BMP in win_filelist.c
#define	WIN_SPECTRUM_L			636
#define	WIN_SPECTRUM_T			85//93
#define	WIN_SPECTRUM_W			278//290
#define	WIN_SPECTRUM_H 			166//160

#define	WIN_SPECTRUM_BAR_L		(WIN_SPECTRUM_L+18)
#define	WIN_SPECTRUM_BAR_W		32//20

#define	WIN_SPECTRUM_BAR_T		(WIN_SPECTRUM_T+20)
#define	WIN_SPECTRUM_BAR_H 		128//138//128

#define	WIN_SPECTRUM_PEAK_H 	8
#define	WIN_SPECTRUM_PEAK_T		(WIN_SPECTRUM_BAR_T+WIN_SPECTRUM_BAR_H-WIN_SPECTRUM_PEAK_H)

#define	WIN_SPECTRUM_BAR_GAP	4//6

#define  WIN_SPECTUM_BAR_SPLIT (WIN_SPECTRUM_BAR_W+WIN_SPECTRUM_BAR_GAP)
    
/*******************************************************************************
*	Function decalare
*******************************************************************************/

static BOOL update_win_spectrum();
static BOOL mute_win_spectrum();

/*******************************************************************************
*	Objects Macro
*******************************************************************************/
#define LDEF_CON(varWnd,nxtObj,focusID,l,t,w,h)		\
		DEF_CONTAINER(varWnd,NULL,nxtObj,C_ATTR_ACTIVE,0, \
	    0,0,0,0,0, l,t,w,h, SPECTRUM_CON_SH_IDX,SPECTRUM_CON_SH_IDX,SPECTRUM_CON_SH_IDX,SPECTRUM_CON_SH_IDX,   \
	    NULL,NULL,  \
	    nxtObj, focusID,0)

#define LDEF_SPECTRUM_BAR(root,varBar,nxtObj,l,t,w,h,rcl,rct,rcw,rch,fsh)	\
		DEF_PROGRESSBAR(varBar, root, nxtObj, C_ATTR_ACTIVE, 0, \
		0,0,0,0,0, l,t,w,h, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX,\
		NULL, NULL, \
		PROGRESSBAR_VERT_REVERSE|PBAR_STYLE_RECT_STYLE, 0, 0, B_BG_SH_IDX, fsh, \
		rcl,rct,rcw,rch, BAR_MIN_POS, BAR_MAX_POS, BAR_MAX_POS, 0)

#define LDEF_SPECTRUM_PEAK(root,varBmp,nxtObj,l,t,w,h)	\
		DEF_BITMAP(varBmp, root, nxtObj, C_ATTR_ACTIVE, 0, \
		0,0,0,0,0, l,t,w,h, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX,\
		NULL, NULL, \
		C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, IM_SPECTRAM_BLUE)

/*******************************************************************************
*   WINDOW's objects defintion
*******************************************************************************/
LDEF_CON(spectrum_con, &spectrum_bar_0, 0, WIN_SPECTRUM_L, WIN_SPECTRUM_T, WIN_SPECTRUM_W, WIN_SPECTRUM_H)

LDEF_SPECTRUM_BAR(&spectrum_con,  spectrum_bar_0, &spectrum_peak_0, \
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*0, WIN_SPECTRUM_BAR_T, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, \
		0, 0, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, B_MID_SH_IDX)

LDEF_SPECTRUM_PEAK(&spectrum_con,spectrum_peak_0,&spectrum_bar_1,\
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*0,	WIN_SPECTRUM_PEAK_T,WIN_SPECTRUM_BAR_W,WIN_SPECTRUM_PEAK_H)

LDEF_SPECTRUM_BAR(&spectrum_con,  spectrum_bar_1, &spectrum_peak_1, \
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*1, WIN_SPECTRUM_BAR_T, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, \
		0, 0, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, B_MID_SH_IDX)

LDEF_SPECTRUM_PEAK(&spectrum_con,spectrum_peak_1,&spectrum_bar_2,\
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*1,	WIN_SPECTRUM_PEAK_T,WIN_SPECTRUM_BAR_W,WIN_SPECTRUM_PEAK_H)

LDEF_SPECTRUM_BAR(&spectrum_con,  spectrum_bar_2, &spectrum_peak_2, \
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*2, WIN_SPECTRUM_BAR_T, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, \
		0, 0, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, B_MID_SH_IDX)

LDEF_SPECTRUM_PEAK(&spectrum_con,spectrum_peak_2,&spectrum_bar_3,\
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*2,	WIN_SPECTRUM_PEAK_T,WIN_SPECTRUM_BAR_W,WIN_SPECTRUM_PEAK_H)

LDEF_SPECTRUM_BAR(&spectrum_con,  spectrum_bar_3, &spectrum_peak_3, \
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*3, WIN_SPECTRUM_BAR_T, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, \
		0, 0, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, B_MID_SH_IDX)

LDEF_SPECTRUM_PEAK(&spectrum_con,spectrum_peak_3,&spectrum_bar_4,\
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*3,	WIN_SPECTRUM_PEAK_T,WIN_SPECTRUM_BAR_W,WIN_SPECTRUM_PEAK_H)

LDEF_SPECTRUM_BAR(&spectrum_con,  spectrum_bar_4, &spectrum_peak_4, \
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*4, WIN_SPECTRUM_BAR_T, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, \
		0, 0, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, B_MID_SH_IDX)

LDEF_SPECTRUM_PEAK(&spectrum_con,spectrum_peak_4,&spectrum_bar_5,\
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*4,	WIN_SPECTRUM_PEAK_T,WIN_SPECTRUM_BAR_W,WIN_SPECTRUM_PEAK_H)

LDEF_SPECTRUM_BAR(&spectrum_con,  spectrum_bar_5, &spectrum_peak_5, \
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*5, WIN_SPECTRUM_BAR_T, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, \
		0, 0, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, B_MID_SH_IDX)

LDEF_SPECTRUM_PEAK(&spectrum_con,spectrum_peak_5,&spectrum_bar_6,\
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*5,	WIN_SPECTRUM_PEAK_T,WIN_SPECTRUM_BAR_W,WIN_SPECTRUM_PEAK_H)

LDEF_SPECTRUM_BAR(&spectrum_con,  spectrum_bar_6, &spectrum_peak_6, \
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*6, WIN_SPECTRUM_BAR_T, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, \
		0, 0, WIN_SPECTRUM_BAR_W, WIN_SPECTRUM_BAR_H, B_MID_SH_IDX)

LDEF_SPECTRUM_PEAK(&spectrum_con,spectrum_peak_6,NULL,\
		WIN_SPECTRUM_BAR_L+WIN_SPECTUM_BAR_SPLIT*6,	WIN_SPECTRUM_PEAK_T,WIN_SPECTRUM_BAR_W,WIN_SPECTRUM_PEAK_H)

/*******************************************************************************
*	Local functions & variables declare
*******************************************************************************/

static spectrum_info spectrum_infor;

PROGRESS_BAR *barlst_items[] =
{
	&spectrum_bar_0,
	&spectrum_bar_1,
	&spectrum_bar_2,
	&spectrum_bar_3,
	&spectrum_bar_4,
	&spectrum_bar_5,
	&spectrum_bar_6,
};

BITMAP *peaklst_items[] =
{
	&spectrum_peak_0,
	&spectrum_peak_1,
	&spectrum_peak_2,
	&spectrum_peak_3,
	&spectrum_peak_4,
	&spectrum_peak_5,
	&spectrum_peak_6,
};

static init_bars(void)
{
	UINT16 i;
	
	for(i=0; i<SPECTRUM_BAR_CNT; i++)
	{
		spectrum_infor.bar_peak[i] = 0;
		spectrum_infor.bar_step[i] = SPECTRUM_BAR_STEP;
		spectrum_infor.bar_precent[i] = 0;
	}
}

static calc_bars(void)
{
	static UINT16 i, val_i = 0;

	// calc peak of bar
	for(i=0; i<SPECTRUM_BAR_CNT; i++)
	{
		if(spectrum_infor.bar_precent[i] > spectrum_infor.bar_peak[i]) // is new peak?
		{
			spectrum_infor.bar_peak[i] = spectrum_infor.bar_precent[i];
			// reset step
			spectrum_infor.bar_step[i] = SPECTRUM_BAR_STEP;
		}
		else
		{
			INT32 val = spectrum_infor.bar_peak[i] - spectrum_infor.bar_step[i];

			if(val < 0)
				val = 0;

			if(val < spectrum_infor.bar_precent[i])
			{
				spectrum_infor.bar_peak[i] = (UINT16)spectrum_infor.bar_precent[i];
				// reset step
				spectrum_infor.bar_step[i] = SPECTRUM_BAR_STEP;				
			}
			else
			{
				spectrum_infor.bar_peak[i] = (UINT16)val;
				spectrum_infor.bar_step[i] = spectrum_infor.bar_step[i]*2;
			}
		}
		
	}
}

void update_bars(UINT32 param)
{
	if(GetMuteState())
	{
		mute_win_spectrum();
	}
	else
	{
		// calc
		calc_bars();
		// update bars
		update_win_spectrum();
	}
}

static void update_callback(UINT32 param)
{
	static UINT16 count = 0;
	INT32 * precent = (INT32 *)param;

	count++;
	if(count%3 == 0)
	{
#ifdef DUAL_ENABLE
        osal_cache_invalidate(precent, sizeof(spectrum_infor.bar_precent));
#endif
		MEMCPY(spectrum_infor.bar_precent, precent, sizeof(spectrum_infor.bar_precent));
		ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SPECTRUM_UPDATE,param,FALSE);
		osal_task_sleep(5);
	}
}

typedef void (*spectrum_callback)(INT32*);

BOOL open_spectrum_dev()
{
	spec_param param;

	init_bars();

	param.collumn_num = SPECTRUM_BAR_CNT;
	param.spec_call_back = (spectrum_callback)update_callback;
		
	snd_io_control(g_snd_dev, SND_SPECTRUM_START, (UINT32)&param);
	
	return TRUE;
}


BOOL close_spectrum_dev()
{
	snd_io_control(g_snd_dev, SND_SPECTRUM_STOP, 0);
}

#if 0
BOOL update_win_spectrum()
{
	UINT16 i, val;
	POBJECT_HEAD pObj;
	PPROGRESS_BAR pBar;

	pObj = (POBJECT_HEAD)&spectrum_bar_con;

	for(i=0; i<SPECTRUM_BAR_CNT; i++)
	{
		OSD_MoveObject(pObj,WIN_SPECTRUM_BAR_L+i*WIN_SPECTUM_BAR_SPLIT,WIN_SPECTRUM_BARCON_T,0);
		val = (bar_precent[i]*TOTAL_BLOCKS)/SPEC_MAX;

/*		pBar = &spectrum_bar_0;
		OSD_SetProgressBarValue(pBar, BAR_MAX_POS);
		pBar = &spectrum_bar_1;
		OSD_SetProgressBarValue(pBar, BAR_MAX_POS);
		pBar = &spectrum_bar_2;
		OSD_SetProgressBarValue(pBar, BAR_MAX_POS);
*/
		if(val <= BAR2_BLOCKS)
		{
			pBar = &spectrum_bar_0;
			OSD_SetProgressBarValue(pBar, 0);
			pBar = &spectrum_bar_1;
			OSD_SetProgressBarValue(pBar, 0);
			pBar = &spectrum_bar_2;
			OSD_SetProgressBarValue(pBar, (val*BAR_MAX_POS)/BAR2_BLOCKS);
		}
		else if(val <= (BAR2_BLOCKS+BAR1_BLOCKS))
		{
			pBar = &spectrum_bar_0;
			OSD_SetProgressBarValue(pBar, 0);
			pBar = &spectrum_bar_1;
			OSD_SetProgressBarValue(pBar, (val-BAR2_BLOCKS)*BAR_MAX_POS/BAR1_BLOCKS);
			pBar = &spectrum_bar_2;
			OSD_SetProgressBarValue(pBar, BAR_MAX_POS);
		}
		else
		{
			if(val > TOTAL_BLOCKS)
				val = TOTAL_BLOCKS;
			pBar = &spectrum_bar_0;
			OSD_SetProgressBarValue(pBar, (val-BAR1_BLOCKS-BAR2_BLOCKS)*BAR_MAX_POS/BAR0_BLOCKS);
			pBar = &spectrum_bar_1;
			OSD_SetProgressBarValue(pBar, BAR_MAX_POS);
			pBar = &spectrum_bar_2;
			OSD_SetProgressBarValue(pBar, BAR_MAX_POS);
		}
		
		OSD_DrawObject(pObj, C_UPDATE_ALL);
	}
	return TRUE;
}

#else

static BOOL update_win_spectrum()
{
	UINT16 i, val;
	POBJECT_HEAD pObj;
	PPROGRESS_BAR pBar;
	PBITMAP		pBmp;

	pObj = (POBJECT_HEAD)&spectrum_con;

	for(i=0; i<SPECTRUM_BAR_CNT; i++)
	{
		pBar = barlst_items[i];
		val = spectrum_infor.bar_precent[i];
		OSD_SetProgressBarValue(pBar,val);

		pBmp = peaklst_items[i];
		OSD_MoveObject((POBJECT_HEAD)pBmp,WIN_SPECTRUM_BAR_L+i*WIN_SPECTUM_BAR_SPLIT,WIN_SPECTRUM_PEAK_T-((spectrum_infor.bar_peak[i]*120)/100),0);
	}

	OSD_DrawObject(pObj, C_UPDATE_ALL);
	return TRUE;
}

static BOOL mute_win_spectrum()
{
	UINT16 i, val;
	POBJECT_HEAD pObj;
	PPROGRESS_BAR pBar;
	PBITMAP		pBmp;

	pObj = (POBJECT_HEAD)&spectrum_con;

	for(i=0; i<SPECTRUM_BAR_CNT; i++)
	{
		pBar = barlst_items[i];
		OSD_SetProgressBarValue(pBar,0);

		pBmp = peaklst_items[i];
		OSD_MoveObject((POBJECT_HEAD)pBmp,WIN_SPECTRUM_BAR_L+i*WIN_SPECTUM_BAR_SPLIT,WIN_SPECTRUM_PEAK_T,0);
	}

	OSD_DrawObject(pObj, C_UPDATE_ALL);
	return TRUE;
}

#endif

#endif

